package com.psds.quartz;

import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.web.context.ContextLoaderListener;
import org.springframework.web.context.WebApplicationContext;

import javax.servlet.ServletContextEvent;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URI;
import java.util.List;

/**
 * author: cjianquan
 * date: 2016/8/29
 */
public class CustContextLoaderListener extends ContextLoaderListener {

    public  CustContextLoaderListener (){

    }

    public  CustContextLoaderListener (WebApplicationContext context){
        super(context);
    }

    /**
     * Initialize the root web application context.
     */
    @Override
    public void contextInitialized(ServletContextEvent event) {
        System.out.println("before initWebApplicationContext===================================");
        //初始化web容器之前，从数据库读取定义任务的配置，并保存到spring-quartz.xml
        initQuartz();

        initWebApplicationContext(event.getServletContext());
        System.out.println("after initWebApplicationContext===================================");
    }

    /**
     * 初始化web容器之前，从数据库读取定义任务的配置，并保存到spring-quartz.xml
     */
    private void initQuartz(){
        //初始化bean
        ClassPathXmlApplicationContext xml = new ClassPathXmlApplicationContext(new String[]{"applicationContext*.xml"});
        QuartzService quartzService = (QuartzService)xml.getBean("quartzService");
        //获取定时任务的配置信息
        List<QuartzEntity> quartzList = null;
        try{
            quartzList  =  quartzService.getQuartzList();
        }catch (Exception e){
            //获取数据库数据异常，直接返回，保持原有的spring-quartz.xml内容
            return;
        }

        Document document = null;
        File file = null;
        SAXReader saxReader = new SAXReader();

        try {
            URI url = CustContextLoaderListener.class.getClassLoader().getResource("spring-quartz.xml").toURI();
            file = new File(url.getPath());
            document = saxReader.read(new FileInputStream(file));
        } catch (Exception e) {
            //获取文件异常，直接返回，保持原有的spring-quartz.xml内容
            return;
        }

        Element root = document.getRootElement();

        root.clearContent();

        Element desc = root.addElement("description");
        desc.addText("quartz");

        Element task = root.addElement("bean");
        task.addAttribute("id","commonQuartz");
        task.addAttribute("class","com.psds.quartz.CommonQuartz");


//        List<Element> beans = root.elements();

//        Element schedulerBean = null;

        //对已存在的任务进行更新
//        for(QuartzEntity quartz:quartzList){
//            String jobname = quartz.getQuartzJobname();
//            String triname = quartz.getQuartzTriname();
//            boolean flag = false;
//            for(Element element:beans){
//                if(element.attribute("id")!=null){
//                    String id = element.attribute("id").getValue();
//                    if(id.equals(jobname)){
//                        /**
//                         * job格式如下，各元素顺序不能变，所以取元素直接下标定死
//                         <bean id="checkOrder" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
//                         <property name="targetObject" ref="task" />
//                         <property name="targetMethod" value="run" />
//                         <property name="arguments">
//                         <value>http://localhost:8080/pspay/api/checkOrderTask/checkOrder1</value>
//                         </property>
//                         </bean>
//                         */
//                        Element e1 = (Element)element.elements().get(2);
//                        Element e2 = (Element)e1.elements().get(0);
//                        e2.setText(quartz.getQuartzJoburl());
//                        flag = true;
//                    }else if(id.equals(triname)){
//                        /**
//                         * trigger格式固定如下：
//                         <bean id="checkOrderTri" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
//                         <property name="jobDetail" ref="checkOrder222" />
//                         <property name="cronExpression" value="0 0/4 * * * ? 222" />
//                         </bean>
//                         */
//                        Element e1 = (Element)element.elements().get(0);
//                        String ref1 = e1.attribute("ref").getValue();
//                        if(!ref1.equals(jobname)){
//                            e1.attribute("ref").setValue(jobname);
//                        }
//                        Element e2 = (Element)element.elements().get(1);
//                        e2.attribute("value").setValue(quartz.getQuartzCronexp());
//                        flag = true;
//                    }else if(id.equals("scheduler")){
//                        schedulerBean = element;
//                    }
//                }
//            }
//            if(flag){
//                quartz2removeList.add(quartz);
//            }
//        }

//        quartzList.removeAll(quartz2removeList);

        //添加新增的定时任务的bean
        for(QuartzEntity quartz:quartzList){
            addQuartz(root,quartz);
        }

//        root.remove(schedulerBean);

//        quartzList.addAll(quartz2removeList);
        //添加定义触发器的bean
        addScheduleBean(root,quartzList);

        //更新xml内容
        XMLWriter fileWriter = null;
        try {
            OutputFormat xmlFormat = OutputFormat.createPrettyPrint();
            xmlFormat.setEncoding("utf-8");
            fileWriter = new XMLWriter(new FileOutputStream(file),xmlFormat);
            fileWriter.write(document);
        } catch (IOException e) {
            e.printStackTrace();
        }finally{
            try {
                fileWriter.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 添加定义触发器的bean
     * @param root
     * @param quartzList
     */
    private void addScheduleBean(Element root, List<QuartzEntity> quartzList) {
        Element e1 = root.addElement("bean");
        e1.addAttribute("id", "scheduler");
        e1.addAttribute("class", "org.springframework.scheduling.quartz.SchedulerFactoryBean");
        Element p1 = e1.addElement("property");
        p1.addAttribute("name", "triggers");
        Element list = p1.addElement("list");
        for(QuartzEntity quartz:quartzList){
            Element r1 = list.addElement("ref");
            r1.addAttribute("bean",quartz.getQuartzJobname()+"Tri");
        }
        Element p2 = e1.addElement("property");
        p2.addAttribute("name", "autoStartup");
        p2.addAttribute("value", "true");
    }

    /**
     * 添加新增的定时任务的bean
     * @param root
     * @param quartz
     */
    private void addQuartz(Element root,QuartzEntity quartz){
        Element e1 = root.addElement("bean");
        e1.addComment(quartz.getQuartzApp()+":"+quartz.getQuartzJobnameCn());
        e1.addAttribute("id", quartz.getQuartzJobname());
        e1.addAttribute("class", "org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean");
        Element p1 = e1.addElement("property");
        p1.addAttribute("name", "targetObject");
        p1.addAttribute("ref", "commonQuartz");
        Element p2 = e1.addElement("property");
        p2.addAttribute("name", "targetMethod");
        p2.addAttribute("value", "run");
        Element p3 = e1.addElement("property");
        p3.addAttribute("name", "arguments");


        Element a1 = p3.addElement("list");

        Element v1 = a1.addElement("value");
        v1.addText(quartz.getQuartzJoburl());

        Element v2 = a1.addElement("value");
        v2.addText(quartz.getQuartzJobname());

        Element e2 = root.addElement("bean");
        e2.addAttribute("id", quartz.getQuartzJobname()+"Tri");
        e2.addAttribute("class", "org.springframework.scheduling.quartz.CronTriggerFactoryBean");

        Element p4 = e2.addElement("property");
        p4.addAttribute("name", "jobDetail");
        p4.addAttribute("ref", quartz.getQuartzJobname());

        Element p5 = e2.addElement("property");
        p5.addComment(quartz.getQuartzCronexpNote());
        p5.addAttribute("name", "cronExpression");
        p5.addAttribute("value", quartz.getQuartzCronexp());
    }

}
